package jehc.djshi.common.base;

import java.util.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import cn.hutool.core.collection.CollectionUtil;
import jehc.djshi.common.cache.redis.RedisUtil;
import jehc.djshi.common.constant.SessionConstant;
import jehc.djshi.common.entity.*;
import jehc.djshi.common.idgeneration.UUID;
import jehc.djshi.common.session.HttpSessionUtils;
import jehc.djshi.common.thread.ModifyRecordThread;
import jehc.djshi.common.thread.OperateBusinessLogsThread;
import jehc.djshi.common.util.*;
import jehc.djshi.common.util.date.DateUtil;
import jehc.djshi.log.dao.XtLoginLogsDao;
import jehc.djshi.log.model.XtLoginLogs;
import jehc.djshi.oauth.dao.OauthAccountDao;
import jehc.djshi.oauth.model.OauthAccount;
import jehc.djshi.sys.dao.XtAreaRegionDao;
import jehc.djshi.sys.model.XtAreaRegion;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import nl.bitwalker.useragentutils.Browser;
import nl.bitwalker.useragentutils.OperatingSystem;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @Desc Server父类支持
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
public class BaseUtils extends UUID {

	@Autowired
	HttpSessionUtils httpSessionUtils;

	@Autowired
	RedisUtil redisUtil;

	@Autowired
	CommonUtils commonUtils;

	@Autowired
	OauthAccountDao oauthAccountDao;

	@Autowired
	private XtAreaRegionDao xtAreaRegionDao;
	/**
	 * 当前登录者姓名
	 * @return
	 */
	public String getXtUname() {
		try {
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
			return commonUtils.getUname(request);
		} catch (Exception e) {
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	public String getUdId(){
		try {
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
			return commonUtils.getBaseHttpSessionEntity().getUserinfoEntity().getXt_departinfo_id();
		} catch (Exception e) {
			log.error("获取系统用户id出现异常：{0}",e);
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	/**
	 * 当前当前账号编号
	 * @return
	 */
	public String getXtUid() {
		try {
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
			return commonUtils.getAccountId(request);
		} catch (Exception e) {
			log.error("获取系统用户id出现异常：{0}",e);
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	/**
	 * 获取当前用户对象信息
	 *
	 * @return
	 */
	public BaseHttpSessionEntity getBaseHttpSessionEntity() {
		try {
			BaseHttpSessionEntity baseHttpSessionEntity = commonUtils.getBaseHttpSessionEntity();
			return baseHttpSessionEntity;
		} catch (Exception e) {
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	/**
	 * 当前登录者信息
	 * @return
	 */
	public OauthAccountEntity getXtU() {
		try {
			OauthAccountEntity oauthAccountEntity = commonUtils.account();
			return oauthAccountEntity;
		} catch (Exception e) {
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}


	/**
	 * 获取当前用户的数据权限
	 * @return
	 */
	public List<String> systemUandM(){
		try {
			List<String> list = commonUtils.systemUandM();
			return list;
		} catch (Exception e) {
			throw new ExceptionUtil("获取systemUandM出现异常："+e.getMessage());
		}
	}

	/**
	 * 判断当前用户是否为超级管理员
	 *
	 * @return
	 */
	public boolean isAdmin() {
		try {
			return commonUtils.isAdmin();
		} catch (Exception e) {
			throw new ExceptionUtil("获取systemUandM出现异常："+e.getMessage());
		}
	}

	/**
	 * 获取缓存值
	 *
	 * @return
	 */
	public static Object getCache(String key) {
		RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
		ServletContext sc = request.getSession(false).getServletContext();
//		Map<String, Object> map = (Map<String, Object>) sc.getAttribute("sys_message");
//		return map.get(key);
		return (String)sc.getAttribute(key);
	}

	/**
	 * 获取缓存值
	 *
	 * @return
	 */
	public static String getCacheStr(String key) {
		RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
		ServletContext sc = request.getSession().getServletContext();
//		Map<String, Object> map = (Map<String, Object>) sc.getAttribute("sys_message");
//		return (String) map.get(key);
		return (String)sc.getAttribute(key);
	}


	/**
	 * 根据KEY获取平台路径
	 *
	 * @param key
	 * @return
	 */
	public List<PathEntity> getXtPathCache(String key) {
		try {
			List<PathEntity> pathList = commonUtils.getXtPathCache(key);
			return pathList;
		} catch (Exception e) {
			throw new ExceptionUtil("获取PathEntity出现异常："+e.getMessage());
		}
	}



	/**
	 * 添加平台业务操作日志通用 采用put方法目的不走事务控制
	 * @param classname
	 * @param method
	 * @param message
	 */
	public void aBLogs(String classname,String method,String message){
		RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
		OperateBusinessLogsEntity operateBusinessLogsEntity = new OperateBusinessLogsEntity();
		operateBusinessLogsEntity.setXt_operate_b_logsTime(DateUtil.getSimpleDateFormat());
		operateBusinessLogsEntity.setXt_operate_b_logs_id(toUUID());
		operateBusinessLogsEntity.setXt_operate_b_logsModules(classname);
		operateBusinessLogsEntity.setXt_operate_b_logsMethod(method);
		operateBusinessLogsEntity.setXt_userinfo_id(getXtUid());
		operateBusinessLogsEntity.setXt_operate_b_logsResult(message);
		//////////为了性能采用异步
		OperateBusinessLogsThread operateBusinessLogsThread = new OperateBusinessLogsThread(operateBusinessLogsEntity,request);
		new Thread(operateBusinessLogsThread).start();
	}
	/**
	 * 添加平台业务操作日志通用 采用put方法目的不走事务控制
	 * @param classname
	 * @param method
	 * @param message
	 * @param parm
	 */
	public void aBLogs(String classname,String method,String message,String parm){
		RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
		OperateBusinessLogsEntity operateBusinessLogsEntity = new OperateBusinessLogsEntity();
		operateBusinessLogsEntity.setXt_operate_b_logsTime(DateUtil.getSimpleDateFormat());
		operateBusinessLogsEntity.setXt_operate_b_logs_id(toUUID());
		operateBusinessLogsEntity.setXt_operate_b_logsModules(classname);
		operateBusinessLogsEntity.setXt_operate_b_logsMethod(method);
		operateBusinessLogsEntity.setXt_userinfo_id(getXtUid());
		operateBusinessLogsEntity.setXt_operate_b_logsResult(message);
		operateBusinessLogsEntity.setXt_operate_b_logsMethodPar(parm);
		//////////为了性能采用异步
		OperateBusinessLogsThread operateBusinessLogsThread = new OperateBusinessLogsThread(operateBusinessLogsEntity,request);
		new Thread(operateBusinessLogsThread).start();
	}

	/**
	 * 执行变更记录
	 * @param <T>
	 * @param oldT
	 * @param newT
	 * @param modules
	 * @param business_id
	 */
	public <T> void aRecord(T oldT, T newT, String modules,String business_id){
		try {
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
			JSONObject oldJson = JsonUtil.toJsonObj(oldT);
			JSONObject newJson = JsonUtil.toJsonObj(newT);
			List<ModifyRecordEntity> list = new ArrayList<ModifyRecordEntity>();
			Iterator iterator = oldJson.keys();
			while(iterator.hasNext()){
				String key = (String) iterator.next();
				String oldV = oldJson.getString(key);
				String newV = newJson.getString(key);
				if(!oldV.equals(newV)){
					ModifyRecordEntity record = new ModifyRecordEntity();
					record.setXt_modify_record_aftervalue(""+newV);
					record.setXt_modify_record_beforevalue(""+oldV);
					record.setXt_modify_record_ctime(DateUtil.getSimpleDateFormat());
					record.setXt_modify_record_field(key);
					record.setXt_modify_record_modules(modules);
					list.add(record);
				}
			}
			for(int i = 0; i < list.size(); i++){
				list.get(i).setXt_modify_record_id(toUUID());
				list.get(i).setBusiness_id(business_id);
				list.get(i).setXt_userinfo_id(getXtUid());
			}
			ModifyRecordThread modifyRecordThread = new ModifyRecordThread(list,request);
			new Thread(modifyRecordThread).start();
		} catch (Exception e) {
		}
	}

	/**
	 * 执行变更记录并过滤字段
	 * @param <T>
	 * @param oldT
	 * @param newT
	 * @param modules
	 * @param business_id
	 * @param fieldList
	 */
	public <T> void aRecord(T oldT, T newT, String modules,String business_id,List<String> fieldList){
		try {
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
			JSONObject oldJson = JsonUtil.toJsonObj(oldT);
			JSONObject newJson = JsonUtil.toJsonObj(newT);
			List<ModifyRecordEntity> list = new ArrayList<ModifyRecordEntity>();
			Iterator iterator = oldJson.keys();
			while(iterator.hasNext()){
				String key = (String) iterator.next();
				if(!fieldList.isEmpty() && fieldList.size() > 0){
					for(String field:fieldList){
						if(field.equals(key)){
							String oldV = oldJson.getString(key);
							String newV = newJson.getString(key);
							if(!oldV.equals(newV)){
								ModifyRecordEntity record = new ModifyRecordEntity();
								record.setXt_modify_record_aftervalue(""+newV);
								record.setXt_modify_record_beforevalue(""+oldV);
								record.setXt_modify_record_ctime(DateUtil.getSimpleDateFormat());
								record.setXt_modify_record_field(key);
								record.setXt_modify_record_modules(modules);
								list.add(record);
							}
						}
					}
				}
			}
			for(int i = 0; i < list.size(); i++){
				list.get(i).setXt_modify_record_id(toUUID());
				list.get(i).setBusiness_id(business_id);
				list.get(i).setXt_userinfo_id(getXtUid());
			}
			ModifyRecordThread modifyRecordThread = new ModifyRecordThread(list,request);
			new Thread(modifyRecordThread).start();
		} catch (Exception e) {
		}
	}

	/**
	 * 统一验证错误 通过注解捕捉字段验证错误信息
	 * @param bindingResult
	 * @return
	 */
	public String backFem(BindingResult bindingResult){
		List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < fieldErrorList.size(); i++) {
			FieldError fieldError =fieldErrorList.get(i);
			sb.append("错误字段消息："+fieldError.getField() +" : "+fieldError.getDefaultMessage()+"<br>");
		}
		return sb.toString();
	}

	/**
	 * 判断当前请求是否异步
	 * @param request
	 * @return
	 */
	public static boolean isAjaxReq(HttpServletRequest request){
		String head = request.getHeader("x-requested-with");
		//XMLHttpRequest为异步 Ext.basex为同步 则Ajax拦截
		if((null != head && (head.equalsIgnoreCase("XMLHttpRequest")|| "Ext.basex".equalsIgnoreCase(head)))) {
			return true;
		}
		return false;
	}

	/**
	 * 根据KEY获取平台字典
	 * @param key
	 * @return
	 */
	public List<DataDictionaryEntity> getXtDataDictionaryCache(String key) {
		try {
			return commonUtils.getXtDataDictionaryCache(key);
		} catch (Exception e) {
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	/**
	 * 判断IP是否为黑户
	 * @param ip
	 * @return
	 */
	public boolean getXtIpFrozenCache(String ip){
		try {
			return commonUtils.getXtIpFrozenCache(ip);
		} catch (Exception e) {
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	//随机生成唯一client.id方法
	public static String getClientId(){
		String nums = "";
		String[] codeChars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
				"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
				"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
		for (int i = 0; i < 23; i++)
		{
			int charNum = (int)Math.floor(Math.random() * codeChars.length);
			nums = nums + codeChars[charNum];
		}
		return nums;
	}

	/**
	 * 获取账户更多信息
	 * @param userParamInfo
	 * @return
	 */
	public UserParamInfo infoList(UserParamInfo userParamInfo) {
		try {
			Map<String, Object> condition = new HashMap<>();
			if(!StringUtil.isEmpty(userParamInfo.getAccount_id())){
				condition.put("account_id",userParamInfo.getAccount_id().split(","));
				List<OauthAccount> oauthAccountList = oauthAccountDao.infoList(condition);
				List<UserinfoEntity> userinfoEntities = new ArrayList<>();
				if(CollectionUtil.isNotEmpty(oauthAccountList)){
					for(OauthAccount oauthAccount:oauthAccountList){
						UserinfoEntity userinfoEntity = new UserinfoEntity();
						userinfoEntity.setXt_userinfo_id(oauthAccount.getAccount_id());
						userinfoEntity.setXt_userinfo_name(oauthAccount.getAccount());
						userinfoEntity.setXt_userinfo_realName(oauthAccount.getName());
						userinfoEntities.add(userinfoEntity);
					}
				}
				userParamInfo.setUserinfoEntities(userinfoEntities);
			}
			return userParamInfo;
		} catch (Exception e) {
			throw new ExceptionUtil("获取UserParamInfo出现异常："+e.getMessage());
		}
	}

	/**
	 * 根据账号id查找账户信息
	 * @param accountId
	 * @return
	 */
	public OauthAccountEntity getAccount(String accountId) {
		try {
			if(StringUtil.isEmpty(accountId)){
				return null;
			}
			OauthAccount oauthAccount = oauthAccountDao.getOauthAccountById(accountId);
			OauthAccountEntity oauthAccountEntity = JsonUtil.fromFastJson(oauthAccount,OauthAccountEntity.class);
			return oauthAccountEntity;
		} catch (Exception e) {
			log.error("获取账户异常：{0}",e);
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	/**
	 * 根据 Token查找在线用户
	 * @param token
	 * @return
	 */
	public OauthAccountEntity getOnlineAccount(String token) {
		try {
			if(StringUtil.isEmpty(token)){
				return null;
			}
			String info = getTokenInfo(token);
			BaseHttpSessionEntity baseHttpSessionEntity = JsonUtil.fromAliFastJson(info, BaseHttpSessionEntity.class);
			if(null == baseHttpSessionEntity){
				return null;
			}
			return baseHttpSessionEntity.getOauthAccountEntity();
		} catch (Exception e) {
			log.error("获取在线账户异常：{0}",e);
			return null;
		}
	}

	/**
	 * 根据 account_id查找在线用户Token
	 * @param account_id
	 * @return
	 */
	public BaseResult getOnlineAccountToken(String account_id,HttpHeaders headers) {
		try {
			if(StringUtil.isEmpty(account_id)){
				return null;
			}
			String info = getTokenByAccountId(account_id);
			return new BaseResult(info);
		} catch (Exception e) {
			log.error("获取在线账户Token异常：{0}",e);
			return null;
		}
	}

	/**
	 * 查询行政区域单条记录
	 * @param id
	 * @return
	 */
	public AreaRegionEntity getAreaRegionEntity(String id){
		try {
			if(StringUtil.isEmpty(id)){
				return null;
			}
			XtAreaRegion xtAreaRegion = xtAreaRegionDao.getXtAreaRegionById(id);
			if(null != xtAreaRegion){
				AreaRegionEntity areaRegionEntity = JsonUtil.fromFastJson(xtAreaRegion,AreaRegionEntity.class);
				return areaRegionEntity;
			}

			return null;
		} catch (Exception e) {
			log.error("查询行政区域单条记录出现异常：{0}",e);
			throw new ExceptionUtil(e.getMessage(),e.getCause());
		}
	}

	/**
	 * 登录日志
	 * @param loginLogsEntity
	 */
	public void loginLogs(LoginLogsEntity loginLogsEntity){
		try {
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
			loginLogsEntity.setXt_login_logIP(request.getRemoteAddr());
			UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
			Browser browser = userAgent.getBrowser();
			OperatingSystem os = userAgent.getOperatingSystem();
			loginLogsEntity.setXt_login_log_browser_name(browser.getName());
			loginLogsEntity.setXt_login_log_browser_type(browser.getBrowserType().getName());
			loginLogsEntity.setXt_login_log_system(os.getName());
			if(null != userAgent.getBrowserVersion()){
				loginLogsEntity.setXt_login_log_browser_version(userAgent.getBrowserVersion().getVersion());
			}
			Runnable loginLogsRunnble = new LoginLogsRunnble(loginLogsEntity,request);
			Thread thread = new Thread(loginLogsRunnble);
			thread.start();
		}catch (Exception e){
			log.error("添加登录日志异常：{}-{}",e,loginLogsEntity);
		}
	}

	class LoginLogsRunnble implements Runnable{
		LoginLogsEntity loginLogsEntity;
		HttpServletRequest request;
		public LoginLogsRunnble(){

		}

		public LoginLogsRunnble(LoginLogsEntity loginLogsEntity,HttpServletRequest request){
			this.loginLogsEntity = loginLogsEntity;
			this.request = request;
		}
		public void run() {
			XtLoginLogsDao xtLoginLogsDao = SpringUtils.getBean(XtLoginLogsDao.class);
			int i = xtLoginLogsDao.addXtLoginLogs(JsonUtil.fromFastJson(loginLogsEntity, XtLoginLogs.class));
			if(i>0){
				log.info("添加登录日志成功：{}",loginLogsEntity);
			}else{
				log.info("添加登录日志失败：{}",loginLogsEntity);
			}
		}
	}

	/**
	 * 获取tokeninfo信息
	 * @param token
	 * @return
	 */
	public String getTokenInfo(String token) {
		return httpSessionUtils.getAttribute(SessionConstant.TOKEN_STORE_PATH+token);
	}

	/**
	 * 根据account_id获取token
	 * @param account_id
	 * @return
	 */
	public String getTokenByAccountId(String account_id){
		if(StringUtils.isEmpty(account_id)){
			return null;
		}
		String token = httpSessionUtils.getAttribute(SessionConstant.ACCOUNT_STORE_PATH+account_id);
		return token;
	}
}
